from tkinter import *
from tkinter import ttk, font, filedialog as fd
import shutil, os, ctypes, pyglet
from fractions import Fraction
from PIL import ImageTk, Image, ImageOps, ImageDraw, ImageFont
import Program
from Edit_recipe_instructions_frame import Edit_recipe_instructions_frame
import Recipes_frame
import Side_frame
from Ingredient import Ingredient
from Recipe import Recipe
from Edit_and_add_ingredients import Edit_and_add_ingredients

class Edit_and_add_recipes(Frame):
    """
    Purpose:
        Frame to modify and create new recipes
    Instance variables:
        self.image_frame: Frame to display or add an image to a recipe
        self.image_of_recipe_label: Label to display image of recipe
        self.add_image_button: button to add an image to a recipe
        self.choose_new_image_button: button to change the image of a recipe
        self.delete_image_button: button to delete the image from a recipe
        self.recipe_combo_box: combo box to select/create recipes
        self.recipe_instructions_label_frame: frame to hold recipe instructions
        self.recipe_instructions_label: label for snippet of recipe instructions
        self.middle_frames_dict: frame containing ingredient in recipe labels
        self.add_new_label: label about adding new ingredient
        self.middle_frames: frame containing ingredients labels
        self.left_frame: left-most column of ingredients labels
        self.first_divider_line: first line seperating ingredient labels
        self.center_frame: center column of ingredients labels
        self.second_divider_line: second line seperating ingredient labels
        self.right_frame: right-most column of ingredients labels
        self.frames: list of left center and right frames
        self.amount_text_box: text box containing amount of ingredient
        self.unit_combo_box: combo box of the unit the ingredient is in,
            either ("Unit", "Tsp", "Tbs", "Oz", "Cup", "Lb")
        self.new_ingredient_combo_box: combo box for adding an
            ingredient to the recipe
        self.add_ingredient_amount_text_box: amount of the ingredient when adding new
        self.add_ingredient_unit_combo_box: unit combo box for adding an ingredient
        self.add_ingredient_add_button: button to add new ingredient
        self.create_ingredient_button: button to create a new ingredient if it
            doesnt exist
        self.lower_middle_frame: frame that has the remove ingredient button
        self.remove_button: removes an ingredient from the recipe
        self.lower_frame: frame that has add, rename, delete recipe buttons
        self.delete_recipe_button: button that deletes the recipe from the program
        self.create_recipe_button: button that creates a new recipe
        self.rename_recipe_button: button that renames a recipe
        self.rename_text_frame: frame that has the widgets to rename a recipe
        self.cancel_rename_button: button that cancels the renaming process
        self.rename_entry_box: entry box to enter the new name of the recipe
        self.rename_done_button: button that finishes the renaming process
    Methods:
        rename_recipe_process: method that handles renaming a recipe
        update_rename_button: method checks if the rename name is a current recipe,
            if it is a done button is not displayed. If it isnt a done button
            is displayed
        recipe_combo_box_clicked_event: toggles the bool of the recipe combo box
            being clicked
        delete_image_button_clicked: deletes the image of a recipe
        add_image_button_clicked: handles adding an image to a recipe
        set_image: finds and displays an image of the recipe
        update_instructions: handles displaying recipe instructions
        add_ingredients_labels: adds the labels to display the recipe ingredients
        label_clicked: handles what happens when an ingredient label is clicked
        add_text_box_and_combo_box: displays the text box and combo box for adding
            a new ingredient
        delete_text_box_and_combo_box: deletes the texts box and combo box of
            a current ingredient
        update_ingredient_unit: changes and saves with a new unit of the ingredient
        update_ingredient_amount: changes and saves with a new amount of the ingredient
        remove_button_clicked: handles removing an ingredient from a recipe
        add_widgets_for_adding_ingredient: displays needed widgets to add an ingredient
        remove_widgets_for_adding_ingredients: removes the widgets that were
            viewable due to adding an ingredient
        update_add_ingredients: updates window due to an ingredient being added
        update_ingredients_combo_box: updates values of the combo box to
            display correct ingredients
        update_add_ingredient_buttons: changes buttons for adding ingredients
            depending on if the typed ingredient exists
        add_button_clicked: handles adding an ingredient to the recipe
        delete_add_ingredients_buttons: removes buttons to add ingredients
        update_recipe_combo_box: updates recipe combo box to display correct recipes
        update_window: updates the window to correctly display recipe information
        change_frame_to_add_ingredient: displays add ingredient frame if a
            ingredient doesnt exist
        create_recipe_clicked: creates a new recipe with the provided name
        delete_recipe_clicked: opens a window to confirm deleting a recipe
        delete_recipe_process: deletes a recipe from the program
        edit_insturctions_clicked: opens a window to edit the recipe instructions
    """

    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.secondary_color_text = "black"
        self.secondary_color_clicked = "light gray"
        self.secondary_color_clicked_text = "black"
        self.primary_color = "SystemButtonFace"
        self.primary_color_text = "black"
        self.bg_color = "SystemButtonFace"
        self.combo_box_style = ttk.Style()
        self.combo_box_style.theme_use("alt")
        self.create_ingredient_button_image = None
        self.add_ingredient_add_button_image = None

        self.image_frame = Frame(self)
        self.image_frame.pack()
        self.image_of_recipe_label = Label(self.image_frame)
        self.image_of_recipe_label.grid(row=0, column=0, padx=5)
        self.add_image_button = Button(
            self.image_frame,
            text="Add Image",
            command=lambda: self.add_image_button_clicked(),
        )
        self.add_image_button.grid(row=0, column=1, padx=5)

        self.choose_new_image_button = Button(
            self.image_frame,
            text="Choose New Image",
            command=lambda: self.add_image_button_clicked(),
        )
        self.choose_new_image_button.grid(row=0, column=1, padx=5)
        self.delete_image_button = Button(
            self.image_frame,
            text="Delete Image",
            command=lambda: self.delete_image_button_clicked(),
        )
        self.delete_image_button.grid(row=0, column=2, padx=5)

        self.recipe_combo_box = ttk.Combobox(self, height=5)
        self.recipe_combo_box.set("Recipe Name")
        self.recipe_combo_box_clicked = False
        self.recipe_combo_box.bind("<KeyRelease>", lambda event: self.update_window())
        self.recipe_combo_box.bind(
            "<<ComboboxSelected>>", lambda event: self.update_window()
        )
        self.recipe_combo_box.bind(
            "<Button-1>",
            lambda event: (
                Program.Program.controller.default_combo_value_clear(
                    self.recipe_combo_box, "Recipe Name"
                ),
                self.recipe_combo_box_clicked_event(),
            )
            if not self.recipe_combo_box_clicked
            else None,
        )
        self.recipe_combo_box.pack()

        self.recipe_instructions_label_frame = Frame(self)
        self.recipe_instructions_label_frame.pack()
        self.recipe_instructions_label = Label(
            self.recipe_instructions_label_frame, wraplength=250, justify="center"
        )
        self.recipe_instructions_label.bind(
            "<Button-1>", lambda event: self.edit_insturctions_clicked()
        )
        self.recipe_instructions_label.pack(fill="x")

        self.middle_frames_dict = {}
        self.add_new_label = None
        self.middle_frames = Frame(self)
        self.middle_frames.pack()
        self.labels_round_corner_overlay = Label(self.middle_frames)
        self.labels_round_corner_overlay.grid(row=0, column=0, columnspan=5, rowspan=1)
        self.left_frame = Frame(self.middle_frames)
        self.left_frame.grid(row=0, column=0, sticky="n", padx=5, pady=5)
        self.first_divider_line = ttk.Separator(self.middle_frames, orient="vertical")
        self.first_divider_line.grid(
            row=0,
            column=1,
            sticky="ns",
        )
        self.center_frame = Frame(self.middle_frames)
        self.center_frame.grid(row=0, column=2, sticky="n", padx=5, pady=5)
        self.second_divider_line = ttk.Separator(self.middle_frames, orient="vertical")
        self.second_divider_line.grid(row=0, column=3, sticky="ns")
        self.right_frame = Frame(self.middle_frames)
        self.right_frame.grid(row=0, column=4, sticky="n", padx=5, pady=5)
        self.frames = [self.left_frame, self.center_frame, self.right_frame]
        self.amount_text_box = None
        self.unit_combo_box = None

        self.new_ingredient_combo_box = None
        self.add_ingredient_amount_text_box = None
        self.add_ingredient_unit_combo_box = None
        self.add_ingredient_add_button = None
        self.create_ingredient_button = None

        self.lower_middle_frame = Frame(self)
        self.lower_middle_frame.pack()
        self.remove_button = Button(
            self.lower_middle_frame,
            text="Remove",
            command=lambda: self.remove_button_clicked(),
        )
        self.remove_button.grid(row=0, column=0, pady=5)
        self.remove_button.grid_remove()

        self.lower_frame = Frame(self)
        self.lower_frame.pack()
        self.delete_recipe_button = Button(
            self.lower_frame,
            text="Delete Recipe",
            command=lambda: self.delete_recipe_clicked(parent),
        )
        self.delete_recipe_button.grid(row=0, column=0, padx=5)
        self.create_recipe_button = Button(
            self.lower_frame,
            text="Create Recipe",
            command=lambda: self.create_recipe_clicked(),
        )
        self.create_recipe_button.grid(row=0, column=0, padx=5)
        self.rename_recipe_button = Button(
            self.lower_frame,
            text="Rename Recipe",
            command=lambda: (
                self.rename_recipe_button.grid_remove(),
                self.rename_text_frame.grid(),
                self.update_rename_button(),
            ),
        )
        self.rename_recipe_button.grid(row=0, column=1, padx=5)
        self.rename_text_frame = Frame(self.lower_frame)
        self.rename_text_frame.grid(row=0, column=1)
        self.cancel_rename_button = Button(
            self.rename_text_frame,
            text="Cancel",
            command=lambda: (
                self.rename_text_frame.grid_remove(),
                self.rename_recipe_button.grid(),
            ),
        )
        self.cancel_rename_button.grid(row=0, column=0, padx=5, pady=5)
        self.rename_entry_box = Entry(self.rename_text_frame, width=20)
        self.rename_entry_box.bind(
            "<KeyRelease>", lambda event: self.update_rename_button()
        )
        self.rename_entry_box.grid(row=0, column=1)
        self.rename_done_button = Button(
            self.rename_text_frame,
            text="Rename",
            command=lambda: (self.rename_recipe_process()),
        )
        self.rename_done_button.grid(row=0, column=2, padx=5, pady=5)

        self.done_button = Button(
            self,
            text="Done",
            command=lambda: (
                Program.Program.controller.change_frames(Recipes_frame.Recipes_frame),
                Program.Program.controller.change_frames(Side_frame.Side_frame, False),
            ),
        )
        self.done_button.pack(side="bottom", pady=(0, 20))

        self.update_window()

    def rename_recipe_process(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "RECIPE NAME":
            recipe_name = ""
        Program.Program.rename_recipe(
            recipe_name,
            self.rename_entry_box.get().capitalize(),
        ),
        self.recipe_combo_box.set(self.rename_entry_box.get()),
        self.rename_entry_box.delete(0, END),
        self.update_window(),
        Program.Program.save("recipes.csv", "ingredients.csv"),

    def update_rename_button(self):
        if Program.Program.search_recipe_name(self.rename_entry_box.get().capitalize()) == None:
            self.rename_done_button.grid()
        else:
            self.rename_done_button.grid_remove()

    def recipe_combo_box_clicked_event(self):
        self.recipe_combo_box_clicked = True

    def delete_image_button_clicked(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        path_to_image = f"{os.getcwd()}\\images\\{recipe_name}.png"
        os.remove(path_to_image)
        self.set_image(path_to_image)

    def add_image_button_clicked(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        image_directory = fd.askopenfilename(filetypes=[("Image png files", "*.png")])
        new_path = f"images\\{recipe_name}.png"
        if image_directory != "" and not (
            os.path.exists(new_path) and os.path.samefile(image_directory, new_path)
        ):
            shutil.copy2(image_directory, new_path)
            self.set_image(new_path)

    def set_image(self, path):
        try:
            if "#" in self.image_of_recipe_label["bg"]:
                color = self.image_of_recipe_label["bg"].upper()
            else:
                color = "#FFFFFF"
            color_rgb = Program.Program.convert_hex_to_rgb(color)
            self.image_of_recipe = Image.open(path)
            self.rounded_corner_overlay = Image.new(
                "RGBA",
                (
                    self.image_of_recipe.width,
                    self.image_of_recipe.height,
                ),
                "#FFFFFF00",
            )
            self.rounded_corner_overlay_draw = ImageDraw.Draw(
                self.rounded_corner_overlay
            )
            self.rounded_corner_overlay_draw.rounded_rectangle(
                (
                    0,
                    0,
                    self.image_of_recipe.width,
                    self.image_of_recipe.height,
                ),
                outline=color + "FF",
                width=3,
                radius=22,
            )
            ImageDraw.floodfill(
                self.rounded_corner_overlay,
                xy=(1, 1),
                value=tuple(list(color_rgb) + [255]),
                thresh=200,
            )
            ImageDraw.floodfill(
                self.rounded_corner_overlay,
                xy=(self.image_of_recipe.width - 1, 1),
                value=tuple(list(color_rgb) + [255]),
                thresh=200,
            )
            ImageDraw.floodfill(
                self.rounded_corner_overlay,
                xy=(
                    self.image_of_recipe.width - 1,
                    self.image_of_recipe.height - 1,
                ),
                value=tuple(list(color_rgb) + [255]),
                thresh=200,
            )
            ImageDraw.floodfill(
                self.rounded_corner_overlay,
                xy=(1, self.image_of_recipe.height - 1),
                value=tuple(list(color_rgb) + [255]),
                thresh=200,
            )
            self.image_of_recipe = Image.alpha_composite(
                self.image_of_recipe, self.rounded_corner_overlay
            )
            self.image_of_recipe = ImageOps.contain(self.image_of_recipe, (70, 70))
            self.image_of_recipe_tkinter = ImageTk.PhotoImage(self.image_of_recipe)
            self.image_of_recipe_label.config(image=self.image_of_recipe_tkinter)
            self.choose_new_image_button.grid()
            self.delete_image_button.grid()
            self.add_image_button.grid_remove()
        except:
            self.image_of_recipe_label.config(image="")
            self.choose_new_image_button.grid_remove()
            self.delete_image_button.grid_remove()
            self.add_image_button.grid()

    def update_instructions(self, recipe_name):
        recipe = Program.Program.search_recipe_name(recipe_name)
        if recipe != None:
            text = recipe.instructions[0:101]
            count_of_newlines = text.count("\n")
            if count_of_newlines > 3:
                last_found = 0
                for i in range(3):
                    last_found = text.find("\n", last_found) + 1
                text = text[:last_found] + "..."
            elif len(text) > 100:
                text = text[0:-1] + "..."
            elif text == "":
                text = "Click to Add Instructions"
            self.recipe_instructions_label.config(text=text)
            self.recipe_instructions_label.pack()
        else:
            self.recipe_instructions_label.config(text="")
            self.recipe_instructions_label.pack_forget()

    def add_ingredients_labels(self, recipe_name):
        for lst in tuple(self.middle_frames_dict.values()):
            lst[0].destroy()
        if self.add_new_label != None:
            self.add_new_label[0].destroy()
            self.add_new_label = None
        self.first_divider_line.grid_remove()
        self.second_divider_line.grid_remove()
        recipe = Program.Program.search_recipe_name(recipe_name)

        if recipe != None:
            self.first_divider_line.grid()
            self.second_divider_line.grid()
            current_num = -1
            for num, ingredient in enumerate(sorted(list(recipe.ingredients.keys()))):
                current_num = num
                column = num % 3
                row = num // 3
                self.middle_frames_dict[ingredient] = [
                    Label(self.frames[column], text=ingredient),
                    row,
                    self.frames[column],
                ]
                self.middle_frames_dict[ingredient][0].bind(
                    "<Button-1>", lambda event: self.label_clicked(event)
                )
                self.middle_frames_dict[ingredient][0].config(
                    bg=self.secondary_color, fg=self.secondary_color_text
                )
                self.middle_frames_dict[ingredient][0].grid(
                    row=row, column=0, sticky="we"
                )
            next_num = current_num + 1
            column = next_num % 3
            row = next_num // 3
            self.add_new_label = [
                Label(
                    self.frames[column],
                    text="Add New",
                    bg=self.secondary_color,
                    fg=self.secondary_color_text,
                ),
                row,
                self.frames[column],
                False,
            ]
            self.add_new_label[0].bind(
                "<Button-1>", lambda event: self.label_clicked(event, True)
            )
            self.add_new_label[0].grid(row=row, column=0, sticky="we")
            if "#" in self["bg"]:
                self.middle_frames.update()
                self.labels_round_corner_overlay_image = (
                    Program.Program.create_rounded_button_image(
                        self["bg"],
                        self.left_frame["bg"],
                        Program.Program.convert_rgb_to_hex(
                            Program.Program.overlay_colors(
                                Program.Program.convert_hex_to_rgb(self.left_frame["bg"]),
                                Program.Program.convert_hex_to_rgb(self.left_frame["bg"]),
                                0,
                            )
                        ),
                        "",
                        int(
                            (
                                self.left_frame.winfo_width()
                                + self.first_divider_line.winfo_width()
                                + self.center_frame.winfo_width()
                                + self.second_divider_line.winfo_width()
                                + self.right_frame.winfo_width()
                                + self.recipe_combo_box.winfo_width()
                            )
                            * 1.3
                        ),
                        int(
                            max(
                                self.left_frame.winfo_height(),
                                self.center_frame.winfo_height(),
                                self.right_frame.winfo_height(),
                            )
                            * 1.5
                        ),
                        22,
                    )
                )
                self.labels_round_corner_overlay.config(
                    image=self.labels_round_corner_overlay_image
                )

    def label_clicked(self, event, add_label_clicked=False):
        if self.selected_label != None:
            if add_label_clicked:
                if self.add_new_label[3]:
                    self.add_new_label[3] = False
                    self.selected_label.configure(
                        bg=self.secondary_color, fg=self.secondary_color_text
                    )
                    self.remove_widgets_for_adding_ingredients()
                    self.selected_label = None
                else:
                    self.selected_label.configure(
                        bg=self.secondary_color, fg=self.secondary_color_text
                    )
                    self.delete_text_box_and_combo_box()
                    self.selected_label = self.add_new_label[0]
                    self.selected_label.configure(
                        bg=self.secondary_color_clicked,
                        fg=self.secondary_color_clicked_text,
                    )
                    self.add_new_label[3] = True
                    self.add_widgets_for_adding_ingredient()
            elif self.add_new_label[3]:
                self.selected_label.configure(
                    bg=self.secondary_color, fg=self.secondary_color_text
                )
                self.remove_widgets_for_adding_ingredients()
                self.add_new_label[3] = False
                self.selected_label = self.middle_frames_dict[
                    event.widget.cget("text")
                ][0]
                self.selected_label.configure(
                    bg=self.secondary_color_clicked,
                    fg=self.secondary_color_clicked_text,
                )
                self.add_text_box_and_combo_box(
                    self.middle_frames_dict[event.widget.cget("text")][1],
                    self.middle_frames_dict[event.widget.cget("text")][2],
                    event.widget.cget("text"),
                )
            elif (
                self.selected_label
                == self.middle_frames_dict[event.widget.cget("text")][0]
            ):
                self.selected_label.configure(
                    bg=self.secondary_color, fg=self.secondary_color_text
                )
                self.delete_text_box_and_combo_box()
                self.selected_label = None
            else:
                self.selected_label.configure(
                    bg=self.secondary_color, fg=self.secondary_color_text
                )
                self.delete_text_box_and_combo_box()
                self.selected_label = self.middle_frames_dict[
                    event.widget.cget("text")
                ][0]
                self.selected_label.configure(
                    bg=self.secondary_color_clicked,
                    fg=self.secondary_color_clicked_text,
                )
                self.add_text_box_and_combo_box(
                    self.middle_frames_dict[event.widget.cget("text")][1],
                    self.middle_frames_dict[event.widget.cget("text")][2],
                    event.widget.cget("text"),
                )
        elif add_label_clicked:
            self.add_new_label[3] = True
            self.selected_label = self.add_new_label[0]
            self.selected_label.configure(
                bg=self.secondary_color_clicked, fg=self.secondary_color_clicked_text
            )
            self.add_widgets_for_adding_ingredient()
        else:
            self.selected_label = self.middle_frames_dict[event.widget.cget("text")][0]
            self.selected_label.configure(
                bg=self.secondary_color_clicked, fg=self.secondary_color_clicked_text
            )
            self.add_text_box_and_combo_box(
                self.middle_frames_dict[event.widget.cget("text")][1],
                self.middle_frames_dict[event.widget.cget("text")][2],
                event.widget.cget("text"),
            )

    def add_text_box_and_combo_box(self, row, frame, ingredient_name):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        recipe = Program.Program.search_recipe_name(recipe_name)
        ingredient_list = recipe.ingredients[ingredient_name]

        self.amount_text_box = Entry(
            frame,
            width=6,
            bg=self.secondary_color_clicked,
            fg=self.secondary_color_clicked_text,
            insertbackground=self.secondary_color_clicked_text,
        )
        self.amount_text_box.bind(
            "<KeyPress>",
            lambda event: Program.Program.only_allow_num_and_equations(event),
        )
        self.amount_text_box.insert(
            0, Program.Program.convert_float_to_string(ingredient_list[0])
        )
        self.amount_text_box.bind(
            "<KeyRelease>", lambda event: self.update_ingredient_amount()
        )
        self.amount_text_box.grid(row=row, column=1)
        unit = ingredient_list[1]

        self.unit_combo_box = ttk.Combobox(
            frame, state="readonly", width=4, style="second_colored.TCombobox"
        )

        self.unit_combo_box.tk.eval(
            f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {self.secondary_color_clicked_text} -background {self.secondary_color_clicked}"
            % self.unit_combo_box
        )
        self.unit_combo_box.bind(
            "<<ComboboxSelected>>", lambda event: self.update_ingredient_unit()
        )
        if unit == "Unit":
            self.unit_combo_box.config(values=("Unit"))
        else:
            self.unit_combo_box.config(values=("Tsp", "Tbs", "Cup", "Oz", "Lb"))
        self.unit_combo_box.set(unit)
        self.unit_combo_box.grid(row=row, column=2)
        self.remove_button.grid()

    def delete_text_box_and_combo_box(self):
        if self.amount_text_box != None:
            self.amount_text_box.destroy()
            self.unit_combo_box.destroy()
            self.amount_text_box = None
            self.unit_combo_box = None
            self.remove_button.grid_remove()

    def update_ingredient_unit(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        recipe = Program.Program.search_recipe_name(recipe_name)
        recipe.ingredients[self.selected_label.cget("text")][
            1
        ] = self.unit_combo_box.get()
        recipe.update_cost()
        Program.Program.save("recipes.csv")

    def update_ingredient_amount(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        recipe = Program.Program.search_recipe_name(recipe_name)
        recipe.ingredients[self.selected_label.cget("text")][
            0
        ] = Program.Program.convert_string_to_float(self.amount_text_box.get())
        recipe.update_cost()
        Program.Program.save("recipes.csv")

    def remove_button_clicked(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        recipe = Program.Program.search_recipe_name(recipe_name)
        del recipe.ingredients[self.selected_label.cget("text")]
        ingredient = Program.Program.search_ingredient_name(self.selected_label.cget("text"))
        ingredient.recipes.discard(recipe.name)
        recipe.update_cost()
        self.update_window()
        Program.Program.save("recipes.csv", "ingredients.csv")
        Program.Program.controller.frames[Recipes_frame.Recipes_frame].refresh_window()

    def add_widgets_for_adding_ingredient(self):
        self.add_new_label[0].grid_remove()
        self.new_ingredient_combo_box = ttk.Combobox(
            self.add_new_label[2], width=15, height=5, style="second_colored.TCombobox"
        )
        self.new_ingredient_combo_box.tk.eval(
            f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {self.secondary_color_clicked_text} -background {self.secondary_color_clicked}"
            % self.new_ingredient_combo_box
        )
        self.new_ingredient_combo_box.bind(
            "<KeyRelease>", lambda event: self.update_add_ingredients()
        )
        self.new_ingredient_combo_box.bind(
            "<<ComboboxSelected>>",
            lambda event: self.update_add_ingredients(),
        )
        self.new_ingredient_combo_box.grid(row=self.add_new_label[1], column=0)
        self.update_add_ingredients()

    def remove_widgets_for_adding_ingredients(self):
        if self.add_new_label != None:
            self.add_new_label[0].grid()
        if self.new_ingredient_combo_box != None:
            self.new_ingredient_combo_box.destroy()
            self.new_ingredient_combo_box = None
        self.delete_add_ingredients_buttons()

    def update_add_ingredients(self):
        if self.new_ingredient_combo_box != None:
            text = self.new_ingredient_combo_box.get().capitalize()
            self.delete_add_ingredients_buttons()
            self.update_ingredients_combo_box(text)
            self.update_add_ingredient_buttons(text)

    def update_ingredients_combo_box(self, text):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "RECIPE NAME":
            recipe_name = ""
        found_ingredients_dict = {}
        for ingredient_name in Ingredient.ingredients_dict:
            if (
                ingredient_name
                not in Program.Program.search_recipe_name(recipe_name).ingredients
            ):
                indx = ingredient_name.upper().find(text.upper())
                if indx != -1:
                    found_ingredients_dict.setdefault(indx, list())
                    found_ingredients_dict[indx].append(ingredient_name)
        self.ingredients_based_on_search_list = []
        for key in sorted(tuple(found_ingredients_dict.keys())):
            self.ingredients_based_on_search_list += sorted(found_ingredients_dict[key])
        self.new_ingredient_combo_box["values"] = self.ingredients_based_on_search_list

    def update_add_ingredient_buttons(self, text):
        ingredient = Program.Program.search_ingredient_name(text)
        if ingredient != None:
            self.add_ingredient_amount_text_box = Entry(
                self.add_new_label[2],
                width=6,
                bg=self.secondary_color_clicked,
                fg=self.secondary_color_clicked_text,
                insertbackground=self.secondary_color_clicked_text,
            )
            self.add_ingredient_amount_text_box.bind(
                "<KeyPress>",
                lambda event: Program.Program.only_allow_num_and_equations(event),
            )
            self.add_ingredient_amount_text_box.grid(
                row=self.add_new_label[1], column=1
            )
            self.add_ingredient_unit_combo_box = ttk.Combobox(
                self.add_new_label[2],
                state="readonly",
                width=4,
                style="second_colored.TCombobox",
            )
            self.add_ingredient_unit_combo_box.tk.eval(
                f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {self.secondary_color_clicked_text} -background {self.secondary_color_clicked}"
                % self.add_ingredient_unit_combo_box
            )
            if ingredient.unit == "Unit":
                self.add_ingredient_unit_combo_box.config(values=("Unit"))
            else:
                self.add_ingredient_unit_combo_box.config(
                    values=("Tsp", "Tbs", "Cup", "Oz", "Lb")
                )
            self.add_ingredient_unit_combo_box.current(0)
            self.add_ingredient_unit_combo_box.grid(row=self.add_new_label[1], column=2)
            self.add_ingredient_add_button = Button(
                self.add_new_label[2],
                text="Add",
                command=lambda: self.add_button_clicked(),
            )
            self.add_ingredient_add_button.grid(
                row=self.add_new_label[1], column=3, padx=5
            )
            if (
                self.add_ingredient_add_button_image == None
                and "#" in self.middle_frames["bg"]
            ):
                self.add_new_label[2].update()
                self.add_ingredient_add_button_image = (
                    Program.Program.create_rounded_button_image(
                        self.secondary_color,
                        self.primary_color,
                        self.primary_color_text,
                        "Add",
                        self.add_ingredient_add_button.winfo_width(),
                        self.add_ingredient_add_button.winfo_height(),
                        22,
                    )
                )
            if self.add_ingredient_add_button_image != None:
                self.add_ingredient_add_button.config(
                    image=self.add_ingredient_add_button_image,
                    border="0",
                    relief="flat",
                    borderwidth=0,
                    highlightthickness=0,
                    activebackground=self.secondary_color,
                )
        else:
            self.create_ingredient_button = Button(
                self.add_new_label[2],
                text="Create Ingredient",
                command=lambda: self.change_frame_to_add_ingredient(),
            )
            self.create_ingredient_button.grid(
                row=self.add_new_label[1], column=1, pady=5
            )
            if (
                self.create_ingredient_button_image == None
                and "#" in self.middle_frames["bg"]
            ):
                self.add_new_label[2].update()
                self.create_ingredient_button_image = (
                    Program.Program.create_rounded_button_image(
                        self.secondary_color,
                        self.primary_color,
                        self.primary_color_text,
                        "Create Ingredient",
                        self.create_ingredient_button.winfo_width(),
                        self.create_ingredient_button.winfo_height(),
                        22,
                    )
                )
            if self.create_ingredient_button_image != None:
                self.create_ingredient_button.config(
                    image=self.create_ingredient_button_image,
                    border="0",
                    relief="flat",
                    borderwidth=0,
                    highlightthickness=0,
                    activebackground=self.secondary_color,
                )

    def add_button_clicked(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        recipe = Program.Program.search_recipe_name(recipe_name)
        recipe.ingredients[self.new_ingredient_combo_box.get().capitalize()] = [
            Program.Program.convert_string_to_float(self.add_ingredient_amount_text_box.get()),
            self.add_ingredient_unit_combo_box.get(),
        ]
        recipe.update_cost()
        ingredient = Program.Program.search_ingredient_name(
            self.new_ingredient_combo_box.get().capitalize()
        )
        ingredient.recipes.add(recipe.name)
        Program.Program.save("recipes.csv", "ingredients.csv")
        self.update_window()
        Program.Program.controller.frames[Recipes_frame.Recipes_frame].refresh_window()

    def delete_add_ingredients_buttons(self):
        if self.add_ingredient_amount_text_box != None:
            self.add_ingredient_amount_text_box.destroy()
            self.add_ingredient_unit_combo_box.destroy()
            self.add_ingredient_add_button.destroy()
            self.add_ingredient_amount_text_box = None
            self.add_ingredient_unit_combo_box = None
            self.add_ingredient_add_button = None
        if self.create_ingredient_button != None:
            self.create_ingredient_button.destroy()
            self.create_ingredient_button = None

    def update_recipe_combo_box(self, current_text):
        found_recipes_dict = {}
        for recipe_name in Recipe.recipes_dict:
            indx = recipe_name.upper().find(current_text.upper())
            if indx != -1:
                found_recipes_dict.setdefault(indx, list())
                found_recipes_dict[indx].append(recipe_name)
        self.recipes_based_on_search_list = []
        for key in sorted(tuple(found_recipes_dict.keys())):
            self.recipes_based_on_search_list += sorted(found_recipes_dict[key])
        self.recipe_combo_box["values"] = self.recipes_based_on_search_list

    def update_window(self):
        self.selected_label = None
        current_text = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and current_text == "Recipe name":
            current_text = ""
        self.delete_text_box_and_combo_box()
        self.remove_widgets_for_adding_ingredients()
        self.update_recipe_combo_box(current_text)
        if Program.Program.search_recipe_name(current_text) != None:
            self.set_image(f"images\\{current_text}.png")
            self.delete_recipe_button.grid()
            self.rename_recipe_button.grid()
            self.rename_text_frame.grid_remove()
            self.create_recipe_button.grid_remove()
        else:
            self.image_of_recipe_label.config(image="")
            self.choose_new_image_button.grid_remove()
            self.delete_image_button.grid_remove()
            self.add_image_button.grid_remove()
            self.delete_recipe_button.grid_remove()
            self.rename_recipe_button.grid_remove()
            self.rename_text_frame.grid_remove()
            self.recipe_instructions_label_frame.config(height=1)
            self.labels_round_corner_overlay.config(image="")
            self.left_frame.config(height=1, width=1)
            self.center_frame.config(height=1, width=1)
            self.right_frame.config(height=1, width=1)
            self.middle_frames.config(height=1, width=1)
            self.lower_middle_frame.config(height=1)
            self.create_recipe_button.grid()
        self.update_instructions(current_text)
        self.add_ingredients_labels(current_text)

    def change_frame_to_add_ingredient(self):
        ingredients_frame = Program.Program.controller.frames[Edit_and_add_ingredients]
        ingredients_frame.ingredients_combo_box.delete(0, END)
        ingredients_frame.ingredients_combo_box.insert(
            0, self.new_ingredient_combo_box.get()
        )
        ingredients_frame.update_combo_box_ingredients()
        ingredients_frame.done_button.config(
            command=lambda: (
                Program.Program.controller.change_frames(Edit_and_add_recipes),
                self.update_add_ingredients(),
                ingredients_frame.done_button.config(
                    command=lambda: (
                        Program.Program.controller.change_frames(Recipes_frame.Recipes_frame),
                        Program.Program.controller.change_frames(Side_frame.Side_frame, False),
                    )
                ),
            )
        )
        Program.Program.controller.change_frames(Edit_and_add_ingredients)

    def create_recipe_clicked(self):
        current_text = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and current_text == "Recipe name":
            current_text = ""
        Program.Program.add_recipe(current_text, {}, "")
        self.update_window()
        Program.Program.save("recipes.csv")
        Program.Program.controller.frames[Recipes_frame.Recipes_frame].refresh_window()

    def delete_recipe_clicked(self, parent):
        recipe_name = self.recipe_combo_box.get()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe Name":
            recipe_name = ""
        Program.Program.controller.bell()
        confirmation_frame = Frame(parent, bg=self.bg_color)
        confirmation_frame.grid(row=0, column=0, sticky="nsew")
        warning_text_color = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb("#CF6679"),
                Program.Program.convert_hex_to_rgb("#000000"),
                0.87,
            ),
        )
        warning_label = Label(
            confirmation_frame,
            text=f"WARNING:\nAre you sure you want to delete the recipe {recipe_name}?\nThis will delete the RECIPE completely.",
            bg="#CF6679",
            fg=warning_text_color,
        )
        warning_label.pack(fill="x")
        lower_frame = Frame(confirmation_frame, bg=self.bg_color)
        lower_frame.pack()
        no_button = Button(
            lower_frame,
            text="No",
            padx=30,
            command=lambda: (confirmation_frame.destroy()),
        )
        no_button.grid(row=0, column=0, padx=5)

        yes_button = Button(
            lower_frame,
            text="Yes",
            bg="red",
            fg="white",
            command=lambda: (
                self.delete_recipe_process(),
                confirmation_frame.destroy(),
            ),
        )
        yes_button.grid(row=0, column=1, padx=5)

        if "#" in self.bg_color:
            lower_frame.update()
            self.no_button_image = Program.Program.create_rounded_button_image(
                self.bg_color,
                self.primary_color,
                self.primary_color_text,
                "No",
                no_button.winfo_width(),
                no_button.winfo_height(),
                22,
            )
            no_button.config(
                border="0",
                relief="flat",
                borderwidth=0,
                highlightthickness=0,
                activebackground=self.bg_color,
                image=self.no_button_image,
            )
            self.yes_button_image = Program.Program.create_rounded_button_image(
                self.bg_color,
                "#CF6679",
                warning_text_color,
                "Yes",
                yes_button.winfo_width(),
                yes_button.winfo_height(),
                22,
            )
            yes_button.config(
                border="0",
                relief="flat",
                borderwidth=0,
                highlightthickness=0,
                activebackground=self.bg_color,
                image=self.yes_button_image,
            )

    def delete_recipe_process(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        Program.Program.delete_recipe(recipe_name)
        path_to_image = f"{os.getcwd()}\\images\\{recipe_name}.png"
        if os.path.exists(path_to_image):
            os.remove(path_to_image)
        self.update_window()
        Program.Program.save("recipes.csv", "ingredients.csv")
        Program.Program.controller.frames[Recipes_frame.Recipes_frame].refresh_window()

    def edit_insturctions_clicked(self):
        recipe_name = self.recipe_combo_box.get().capitalize()
        if not self.recipe_combo_box_clicked and recipe_name == "Recipe name":
            recipe_name = ""
        Program.Program.controller.frames[Edit_recipe_instructions_frame].set_up_screen(
            recipe_name
        )
        Program.Program.controller.change_frames(Edit_recipe_instructions_frame)

    def change_colors(self, bg_color, primary_color, primary_variant, secondary_color):
        self.bg_color = bg_color
        elevation_1_color = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(bg_color), (255, 255, 255), 0.05
            )
        )
        if Program.Program.light_mode:
            button_text_color = "#FFFFFF"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (0, 0, 0), 0.87
                )
            )
        else:
            button_text_color = "#000000"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (255, 255, 255), 0.87
                )
            )
        self.primary_color = primary_color
        self.primary_color_text = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(primary_color),
                Program.Program.convert_hex_to_rgb(button_text_color),
                0.87,
            )
        )
        self.secondary_color = secondary_color
        self.secondary_color_text = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(secondary_color),
                Program.Program.convert_hex_to_rgb(button_text_color),
                0.87,
            )
        )
        self.secondary_color_clicked = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(secondary_color), (255, 255, 255), 0.16
            )
        )
        self.secondary_color_clicked_text = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(self.secondary_color_clicked),
                Program.Program.convert_hex_to_rgb(button_text_color),
                0.87,
            )
        )

        self.add_ingredient_add_button_image = None
        self.create_ingredient_button_image = None
        self.config(bg=bg_color)
        self.recipe_combo_box.configure(
            style="colored.TCombobox",
        )
        self.recipe_combo_box.tk.eval(
            f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {label_color} -background {elevation_1_color}"
            % self.recipe_combo_box
        )

        self.combo_box_style.map(
            "second_colored.TCombobox",
            fieldbackground=[("readonly", self.secondary_color_clicked)],
        )
        self.combo_box_style.configure(
            "second_colored.TCombobox",
            foreground=self.secondary_color_clicked_text,
            fieldbackground=self.secondary_color_clicked,
            background=self.secondary_color,
            insertcolor=self.secondary_color_clicked_text,
            arrowcolor=button_text_color,
        )
        self.image_frame.config(bg=bg_color)
        self.image_of_recipe_label.config(bg=bg_color)
        self.lower_middle_frame.config(bg=bg_color)
        self.lower_frame.config(bg=bg_color)
        self.labels_round_corner_overlay.config(bg=bg_color)
        self.choose_new_image_button.grid()
        self.delete_image_button.grid()
        self.add_image_button.grid()
        self.remove_button.grid()
        self.create_recipe_button.grid()
        self.delete_recipe_button.grid()
        self.rename_recipe_button.grid()
        self.rename_text_frame.grid(),
        self.rename_recipe_button.grid()
        self.update()
        self.choose_new_image_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Choose New Image",
            self.choose_new_image_button.winfo_width(),
            self.choose_new_image_button.winfo_height(),
            22,
        )
        self.choose_new_image_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=elevation_1_color,
            image=self.choose_new_image_button_image,
        )
        self.delete_image_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Delete Image",
            self.delete_image_button.winfo_width(),
            self.delete_image_button.winfo_height(),
            22,
        )
        self.delete_image_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=elevation_1_color,
            image=self.delete_image_button_image,
        )
        self.add_image_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Add Image",
            self.add_image_button.winfo_width(),
            self.add_image_button.winfo_height(),
            22,
        )
        self.add_image_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=elevation_1_color,
            image=self.add_image_button_image,
        )
        self.remove_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            secondary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(secondary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Remove",
            self.remove_button.winfo_width(),
            self.remove_button.winfo_height(),
            22,
        )
        self.remove_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.remove_button_image,
        )
        self.create_recipe_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Create Recipe",
            self.create_recipe_button.winfo_width(),
            self.create_recipe_button.winfo_height(),
            22,
        )
        self.create_recipe_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.create_recipe_button_image,
        )
        self.delete_recipe_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Delete Recipe",
            self.delete_recipe_button.winfo_width(),
            self.delete_recipe_button.winfo_height(),
            22,
        )
        self.delete_recipe_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.delete_recipe_button_image,
        )
        self.rename_recipe_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Rename Recipe",
            self.rename_recipe_button.winfo_width(),
            self.rename_recipe_button.winfo_height(),
            22,
        )
        self.rename_recipe_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.rename_recipe_button_image,
        )
        self.done_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Done",
            self.done_button.winfo_width(),
            self.done_button.winfo_height(),
            22,
        )
        self.done_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.done_button_image,
        )
        self.cancel_rename_button_image = Program.Program.create_rounded_button_image(
            secondary_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Cancel",
            self.cancel_rename_button.winfo_width(),
            self.cancel_rename_button.winfo_height(),
            22,
        )
        self.cancel_rename_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=secondary_color,
            image=self.cancel_rename_button_image,
        )
        self.rename_done_button_image = Program.Program.create_rounded_button_image(
            secondary_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Rename",
            self.rename_done_button.winfo_width(),
            self.rename_done_button.winfo_height(),
            22,
        )
        self.rename_done_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=secondary_color,
            image=self.rename_done_button_image,
        )

        self.remove_button.grid_remove()
        self.rename_text_frame.grid_remove(),

        self.recipe_instructions_label_frame.config(bg=bg_color)
        self.recipe_instructions_label.config(
            bg=elevation_1_color, fg=label_color, borderwidth=1, relief="solid"
        )
        self.middle_frames.config(bg=bg_color)
        self.left_frame.config(bg=secondary_color)
        self.center_frame.config(bg=secondary_color)
        self.right_frame.config(bg=secondary_color)
        self.rename_text_frame.config(bg=secondary_color)
        self.rename_entry_box.config(bg=secondary_color, fg=self.secondary_color_text)
        self.update_window()